﻿module Leaves.NeuroCryptography.KeyGenerators

open Leaves.NeuroCryptography.NeuralNetworks
open Leaves.NeuroCryptography.ChaoticFunctions

type KeyGenerator = {
    mutable Subkeys : list<float>
    Power : int
}

let SubkeysCount = 4

let createUserKeySubkeys (digitalUserKey : list<float>) = 
    if digitalUserKey.Length = 0 then
        failwith "User key should be not empty"
    if digitalUserKey.Length % SubkeysCount <> 0 then
        failwithf "User key length should be a product of %d" SubkeysCount

    let subkeyLength = digitalUserKey.Length / SubkeysCount

    seq {
        for subkeyIndex in 0..(SubkeysCount - 1) do
            yield
                (seq {
                    for index in subkeyIndex * subkeyLength..((subkeyIndex + 1) * subkeyLength - 1) do
                        yield digitalUserKey.[index]
                } |> Seq.sum) % 1.0
    } |> Seq.toList

let CreateKeyGenerator digitalUserKey =
    let subkeys = createUserKeySubkeys digitalUserKey

    {Subkeys = subkeys; Power = DefaultChaoticFunctionPower}

let GetNextGeneratorValue generator index =
    let resultPower = generator.Power + index

    let left = ChaoticFunction generator.Subkeys.[2] resultPower generator.Subkeys.[0]
    let right = ChaoticFunction generator.Subkeys.[3] resultPower generator.Subkeys.[1]

    (left + right) % 1.0

let ReconfigureHashNeuralNetwork generator network =
    let mutable generatorIndex = 0

    for layer in network.Layers do
        for neuron in layer do
            neuron.Function <- ChaoticFunction (GetNextGeneratorValue generator generatorIndex) DefaultChaoticFunctionPower
            generatorIndex <- generatorIndex + 1

            neuron.Bias <- GetNextGeneratorValue generator generatorIndex
            generatorIndex <- generatorIndex + 1

            for input in neuron.Inputs do
                input.Weight <- GetNextGeneratorValue generator generatorIndex
                generatorIndex <- generatorIndex + 1

let ReconfigureKeyGenerator generator newDigitalUserKey =
    let subkeys = createUserKeySubkeys newDigitalUserKey

    generator.Subkeys <- subkeys


